// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SharedSettingsFile.cs" company="Roman '4ux-nbIx' Novitsky">
//   Copyright (c) Roman '4ux-nbIx' Novitsky 2009
// </copyright>
// <summary>
//   Describes and manipulates the shared settings file.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace SettingsManager
{
  #region Namespace Imports

  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;

  using ComponentSettingsManagers;

  using JetBrains.Annotations;
  using JetBrains.ProjectModel;

  using Properties;

  #endregion


  /// <summary>
  /// Describes and manipulates the shared settings file.
  /// </summary>
  internal sealed class SharedSettingsFile : SettingsFile
  {
    #region Constants and Fields

    private readonly ISolution _solution;

    #endregion


    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="SharedSettingsFile"/> class.
    /// </summary>
    /// <param name="solution">
    /// The solution.
    /// </param>
    private SharedSettingsFile([NotNull] ISolution solution)
      : this(solution, solution.GetSettingsFilePath())
    {
    }


    /// <summary>
    /// Initializes a new instance of the <see cref="SharedSettingsFile"/> class.
    /// </summary>
    /// <param name="solution">
    /// The solution.
    /// </param>
    /// <param name="filePath">
    /// The file path.
    /// </param>
    private SharedSettingsFile([NotNull] ISolution solution, [NotNull] string filePath)
      : base(filePath)
    {
      _solution = solution;
    }

    #endregion


    #region Properties


    /// <summary>
    /// Gets the name of the global settings file.
    /// </summary>
    /// <value>
    /// The name of the global settings file.
    /// </value>
    public static string GlobalSettingsFileName
    {
      get
      {
        return Resources.GlobalSettingsFileName + "." + Resources.SettingsFileExtension;
      }
    }


    /// <summary>
    /// Gets the display name.
    /// </summary>
    public override string DisplayName
    {
      get
      {
        return IsGlobal ? Path.Directory.Name : "Current solution settings";
      }
    }


    /// <summary>
    /// Gets a value indicating whether this <see cref="SharedSettingsFile"/> is global.
    /// </summary>
    /// <value>
    /// <c>True</c> if this <see cref="SharedSettingsFile"/> is global; otherwise, <c>false</c>.
    /// </value>
    public bool IsGlobal
    {
      get
      {
        return Path.Name != _solution.GetSettingsFileName();
      }
    }

    /// <summary>
    /// Gets or sets the parent settings file.
    /// </summary>
    /// <value>
    /// The parent settings file.
    /// </value>
    public SharedSettingsFile ParentSettingsFile
    {
      get;
      set;
    }

    #endregion


    #region Public Methods

    /// <summary>
    /// Creates the new file at the specified file path.
    /// </summary>
    /// <param name="solution">
    /// The solution.
    /// </param>
    /// <param name="filePath">
    /// The file path.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="SettingsManager.SettingsFile"/>.
    /// </returns>
    /// <exception cref="InvalidOperationException">
    /// A file at the specified path already exists.
    /// </exception>
    [NotNull]
    public static SharedSettingsFile Create([NotNull] ISolution solution, [CanBeNull] string filePath = null)
    {
      if (File.Exists(filePath))
      {
        throw new InvalidOperationException("A file at the specified path already exists.");
      }

      return filePath == null ? new SharedSettingsFile(solution) : new SharedSettingsFile(solution, filePath);
    }


    /// <summary>
    /// Loads the file at the specified file path.
    /// </summary>
    /// <param name="solution">
    /// The solution.
    /// </param>
    /// <param name="filePath">
    /// The file path.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="SettingsManager.SettingsFile"/>.
    /// </returns>
    [CanBeNull]
    public static SharedSettingsFile Load([NotNull] ISolution solution, [CanBeNull] string filePath = null)
    {
      SharedSettingsFile file = filePath == null
                                  ? new SharedSettingsFile(solution) : new SharedSettingsFile(solution, filePath);

      return file.LoadContents() ? file : null;
    }


    /// <summary>
    /// Loads the resharper settings.
    /// </summary>
    /// <param name="settingsManagers">
    /// The settings managers.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="System.Boolean"/>.
    /// </returns>
    public override bool LoadResharperSettings([NotNull] IEnumerable<IComponentSettingsManager> settingsManagers)
    {
      if (!base.LoadResharperSettings(settingsManagers))
      {
        return false;
      }

      if (ParentSettingsFile != null)
      {
        IEnumerable<IComponentSettingsManager> managers =
          settingsManagers.Where(m => !SettingsManagers.Contains(m));

        if (!managers.Any())
        {
          return true;
        }

        if (!ParentSettingsFile.LoadResharperSettings(managers))
        {
          return false;
        }
      }

      return true;
    }


    /// <summary>
    /// Saves the resharper settings.
    /// </summary>
    /// <param name="settingsManagers">
    /// The settings managers.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="System.Boolean"/>.
    /// </returns>
    public override bool SaveResharperSettings([NotNull] IEnumerable<IComponentSettingsManager> settingsManagers)
    {
      if (!base.SaveResharperSettings(settingsManagers))
      {
        return false;
      }

      if (ParentSettingsFile != null)
      {
        IEnumerable<IComponentSettingsManager> managers =
          settingsManagers.Where(m => !SettingsManagers.Contains(m));

        if (!managers.Any())
        {
          return true;
        }

        if (!ParentSettingsFile.SaveResharperSettings(managers))
        {
          return false;
        }
      }

      return true;
    }


    /// <summary>
    /// Saves the resharper settings.
    /// </summary>
    /// <param name="updateOverriddenFiles">If set to <c>true</c> overridden files will be updated too.</param>
    /// <param name="settingsManagers">The settings managers.</param>
    /// <returns>
    /// Returns an instance of <see cref="System.Boolean"/>.
    /// </returns>
    public bool SaveResharperSettings(bool updateOverriddenFiles, [NotNull] IEnumerable<IComponentSettingsManager> settingsManagers)
    {
      return updateOverriddenFiles ? SaveResharperSettings(settingsManagers) : base.SaveResharperSettings(settingsManagers);
    }


    /// <summary>
    /// Saves the resharper settings.
    /// </summary>
    /// <param name="updateOverriddenFiles">If set to <c>true</c> overridden files will be updated too.</param>
    /// <returns>
    /// Returns an instance of <see cref="System.Boolean"/>.
    /// </returns>
    public bool SaveResharperSettings(bool updateOverriddenFiles)
    {
      IEnumerable<IComponentSettingsManager> settingsManagers =
        ResharperSettingsManager.Instance.ComponentSettingsManagers;

      return updateOverriddenFiles ? SaveResharperSettings(settingsManagers) : base.SaveResharperSettings(settingsManagers);
    }


    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    /// <returns>
    /// A <see cref="System.String"/> that represents this instance.
    /// </returns>
    public override string ToString()
    {
      return string.Format("{0} Shared Settings", _solution.Name);
    }


    /// <summary>
    /// Updates the common settings.
    /// </summary>
    /// <param name="settingsManagers">
    /// The settings managers.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="System.Boolean"/>.
    /// </returns>
    public override bool UpdateCommonResharperSettings([NotNull] IEnumerable<IComponentSettingsManager> settingsManagers)
    {
      if (!base.UpdateCommonResharperSettings(settingsManagers))
      {
        return false;
      }

      if (ParentSettingsFile != null)
      {
        IEnumerable<IComponentSettingsManager> managers =
          settingsManagers.Where(m => !SettingsManagers.Contains(m));

        if (!managers.Any())
        {
          return true;
        }

        if (!ParentSettingsFile.UpdateCommonResharperSettings(managers))
        {
          return false;
        }
      }

      return true;
    }

    #endregion
  }
}